﻿using System.IO;

using System.Diagnostics;
using System.Windows.Forms;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
	 
namespace TileViewer
{
    public partial class RenderControl : GraphicsDeviceControl
    {
        // Simulate the GameTime ourselves because we don't have Game
        GameTime gameTime;
        SpriteBatch sb;
        GraphicsDevice device;
 
        // Elapsed and total time for the GameTime
        Stopwatch elapsedTime = new Stopwatch();
        Stopwatch totalTime = new Stopwatch();
 
        // Timer to keep track of refreshes
        Timer timer;

        public Texture2D Texture;

        public double Zoom;
        public Vector2 Center;
        BasicEffect Effect;
        static VertexPositionColor[] vert = new VertexPositionColor[2];

        public Form1 Otec;

        public RenderControl()
        {
            // Run pre-generated control code
            //InitializeComponent();
 
            // Start the timer keeping track of total elapsed time
            totalTime.Start();
 
            // Hook the mouse down event for the mousedevice, so the control
            // will be selected when clicked on. This avoids problems with
            // mouse and keyboard camera commands affecting other controls on
            // the form
            this.MouseDown += new MouseEventHandler(RenderControl_MouseDown);
        }
	 
        // Select control on mouse down
        void RenderControl_MouseDown(object sender, MouseEventArgs e)
        {
            this.Select();
        }
	 
        // Initialize the Control
        protected override void Initialize()
        {
            // Set up the frame update timer
            timer = new Timer();
	 
            // Lock framerate to 40 so we can keep performance up
            timer.Interval = (int)((1f / 40f) * 1000);
	 
            // Hook timer's tick so we can refresh the view on cue
            timer.Tick += new System.EventHandler(timer_Tick);
            timer.Start();
	        device=((IGraphicsDeviceService)Services.GetService(typeof(IGraphicsDeviceService))).GraphicsDevice;
            sb=new SpriteBatch(device);
            Effect = new BasicEffect(device);
            Effect.VertexColorEnabled = true;

            Zoom = 1;

            Center = new Vector2(0, 0);
        }

        public void LoadTexture(string path)
        {
            if(Texture!=null)Texture.Dispose();
            Texture = Texture2D.FromStream(device, File.OpenRead(path));

            Zoom = 1;

            Center = new Vector2(0, 0);
        }

        // Timer's tick causes the view to refresh
        void timer_Tick(object sender, System.EventArgs e)
        {
            // Invalidate everything so the whole control refreshes
            this.Invalidate();
 
            // Force the view update
            this.Update();
        }
	 
        // Draw the scene
        MouseState st2;

        protected override void Draw()
        {
            if (Texture != null)
            {
                // is this Form active?
                if (Form.ActiveForm == Otec)
                {
                    UpdateGameTime();
                    Mouse.WindowHandle = this.Handle;
                    MouseState st = Mouse.GetState();
                    float k = st.ScrollWheelValue - st2.ScrollWheelValue;

                    if (st.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        Center.X += st.X - st2.X;
                        Center.Y += st.Y - st2.Y;
                    }

                    st2 = st;
                    Zoom += k * 0.001;
                    if (Zoom < 1) Zoom = 1;
                }

                double tr = (int)(device.Viewport.Width / (double)Otec.Count);

                // Update GameTime again and draw the scene
                UpdateGameTime();
                device.Clear(Color.CornflowerBlue);
                sb.Begin();

                for (int i = 0; i < Otec.Count; i++)
                {
                    for (int j = 0; j < Otec.Count; j++)
                    {
                        sb.Draw(Texture, new Rectangle((int)((tr * j * Zoom) + Center.X), (int)((tr * i * Zoom) + Center.Y), (int)(tr * Zoom), (int)(tr * Zoom)), Color.White);
                    }
                }

                sb.End();

                vert[0].Color = Color.Red;
                vert[1].Color = Color.Red;

                if (Otec.ShowGrid)
                {
                    Effect.Techniques[0].Passes[0].Apply();
                    for (int i = 0; i <= Otec.Count; i++)
                    {
                        //lines
                        vert[0].Position.X = -1;
                        vert[0].Position.Y = (float)(2 * (1 - ((i * tr * (Zoom) + Center.Y) / device.Viewport.Height)) - 1);


                        vert[1].Position.X = 1;
                        vert[1].Position.Y = (float)(2 * (1 - ((i * tr * (Zoom) + Center.Y) / device.Viewport.Height)) - 1);
                        device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vert, 0, 1);
                    }

                    for (int i = 0; i <= Otec.Count; i++)
                    {
                        //collums
                        vert[0].Position.X = (float)(2 * (i * tr * Zoom + Center.X) / device.Viewport.Width - 1);
                        vert[0].Position.Y = -1;

                        vert[1].Position.X = (float)(2 * (i * tr * Zoom + Center.X) / device.Viewport.Width - 1);
                        vert[1].Position.Y = 1;
                        device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vert, 0, 1);
                    }
                }
            }
            else
            {
                device.Clear(Color.CornflowerBlue);
            }
        }

        
 
        // Updates the GameTime object instead of relying on Game
        void UpdateGameTime()
        {
            // Recreate the GameTime with the current values
            gameTime = new GameTime(totalTime.Elapsed, elapsedTime.Elapsed);//new GameTime(totalTime.Elapsed, totalTime.Elapsed, elapsedTime.Elapsed, elapsedTime.Elapsed);
 
            // Restart the elapsed timer that keeps track of time between frames
            elapsedTime.Reset();
            elapsedTime.Start();
        }
    }
}